package reaction

import (
	"context"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/resultx"
	"mall/service/forum/model"
	"mall/service/forum/rpc/internal/svc"
	"mall/service/forum/rpc/types/forum"

	// "github.com/volatiletech/null/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type CreateReactionLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewCreateReactionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateReactionLogic {
	return &CreateReactionLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *CreateReactionLogic) CreateReaction(in *forum.ReactionInfo) (*forum.BaseIDResp, error) {
	if in.AuthorId == nil && in.TopicId == nil && in.PostId == nil && in.CommentId == nil {
		return nil, resultx.NewErrCode(resultx.FORUM_REACTION_CONTENT_ID_INVALID)
	}

	if in.Author == nil || in.Author.Id == nil || *in.Author.Id == 0 {
		return nil, resultx.StatusError(resultx.FORUM_REACTION_USER_ID_INVALID, "")
	}

	if in.Type == nil || len(*in.Type) == 0 {
		return nil, resultx.StatusError(resultx.FORUM_REACTION_TYPE_INVALID, "")
	}

	var forumId uint64
	var authorId uint64
	var topicId uint64
	var postId uint64
	if in.TopicId != nil && *in.TopicId > 0 {
		topic, err := l.svcCtx.Topic.FindOne(l.ctx, *in.TopicId)
		if err != nil {
			return nil, err
		}

		if topic.TopicStatus == uint8(globalkey.StatusDeleted) {
			return nil, resultx.StatusError(resultx.FORUM_TOPIC_STATUS_INVALID, "")
		}

		forumId = topic.ForumID
		authorId = topic.TopicAuthorID
		topicId = topic.TopicID
	} else if in.PostId != nil && *in.PostId > 0 {
		post, err := l.svcCtx.Post.FindOne(l.ctx, *in.PostId)
		if err != nil {
			return nil, err
		}

		if post.PostStatus == uint8(globalkey.StatusDeleted) {
			return nil, resultx.StatusError(resultx.FORUM_POST_STATUS_INVALID, "")
		}

		forumId = post.ForumID
		authorId = post.PostAuthorID
		topicId = post.TopicID
		postId = post.PostID
	}

	userId := *in.Author.Id
	now := time.Now() // 本地时间
	gmtNow := modelx.GetGmtTime(now)
	reaction := &model.ForumReaction{
		ReactionUserID:       userId,
		ReactionDate:         now,
		ReactionDateGMT:      gmtNow,
		ReactionModifiedDate: now,
		ReactionModifiedGMT:  gmtNow,
		ReactionStatus:       uint8(globalkey.StatusPending),
	}

	if forumId > 0 {
		reaction.ForumID = forumId
	}
	if authorId > 0 {
		reaction.AuthorID = authorId
	}
	if topicId > 0 {
		reaction.TopicID = topicId
	}
	if postId > 0 {
		reaction.PostID = postId
	}
	if in.ContentHtml != nil && len(strings.TrimSpace(*in.ContentHtml)) > 0 {
		reaction.ReactionContent = strings.TrimSpace(*in.ContentHtml)
	}

	if in.Author.Name != nil {
		reaction.ReactionUser = *in.Author.Name
	}
	if in.Author.Email != nil {
		reaction.ReactionUserEmail = *in.Author.Email
	}
	if in.Author.Avatar != nil {
		reaction.ReactionUserURL = *in.Author.Avatar
	}
	if in.Author.Ip != nil {
		reaction.ReactionUserIP = *in.Author.Ip
	}
	if in.Author.Level != nil {
		reaction.ReactionUserLevel = uint8(*in.Author.Level)
	}
	if in.Author.Anonymous != nil {
		reaction.ReactionUserAnonymous = uint8(*in.Author.Anonymous)
	}

	if in.Type != nil && len(*in.Type) > 0 { // todo:
		// reaction.ReactionType = uint8(1)
	}

	rel := &model.ForumReactionRel{}
	// if len(in.Meta) > 0 {
	// 	for _, v := range in.Meta {
	// 		if v.Key == nil || v.Value == nil || len(strings.TrimSpace(*v.Key)) == 0 || len(strings.TrimSpace(*v.Value)) == 0 {
	// 			continue
	// 		}

	// 		rel.Meta = append(rel.Meta, &model.ForumReactionMetum{
	// 			MetaKey:   strings.TrimSpace(*v.Key),
	// 			MetaValue: null.StringFrom(strings.TrimSpace(*v.Value)),
	// 		})
	// 	}
	// }

	var thumbnailId uint64
	var thumbnailUrl string
	if len(in.NewMedia) > 0 {
		for _, v := range in.NewMedia {
			var url string
			if v.Url != nil && len(*v.Url) > 0 { // 最终网址
				url = *v.Url
			}
			if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 { // 临时网址
				url = *v.Uri
			}
			if len(url) == 0 {
				continue
			}

			var media model.ForumAttachmentRelationship
			if v.Id != nil && len(*v.Id) > 0 {
				if i, err := strconv.ParseInt(*v.Id, 10, 64); err == nil && i > 0 {
					media.AttachmentID = uint64(i)
					if len(thumbnailUrl) == 0 && thumbnailId == 0 {
						thumbnailId = uint64(i)
					}
				}
			}
			if len(thumbnailUrl) == 0 {
				thumbnailUrl = url
			}
			if v.Uri != nil && len(*v.Uri) > 0 {
				media.AttachmentSource = *v.Uri
			}
			media.AttachmentImageURL = url
			if v.Thumbnail != nil && *v.Thumbnail > 0 {
				media.AttachmentThumbnail = uint8(*v.Thumbnail)
			}
			if v.AltText != nil && len(*v.AltText) > 0 {
				media.AttachmentImageAlt = *v.AltText
			}
			if v.Meta != nil && len(*v.Meta) > 0 {
				media.AttachmentImageMeta = *v.Meta
			}
			if v.Order != nil && *v.Order > 0 {
				media.AttachmentOrder = uint(*v.Order)
			}
			rel.Media = append(rel.Media, &media)
		}
	}

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, resultx.StatusError(resultx.DB_ERROR, "")
	}

	err = l.svcCtx.Reaction.Insert(l.ctx, tx, reaction, rel)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	tx.Commit()

	return &forum.BaseIDResp{
		Id: reaction.ReactionID,
	}, nil
}
